;  PROGRAM:  SAK (Strike Any Key)
;  AUTHOR:  Richard Conn
;  VERSION:  1.0
;  DATE:  18 April 1983
;  PREVIOUS VERSIONS:  None
vers	equ	10

;
;	SAK (Strike Any Key) is used for the following purposes:
;		1) to wait for user interaction before continuing
;			and to allow the user to abort a Multiple
;			Command Line
;		2) to command the user's attention by ringing the
;			bell at his console
;
;	The SAK command line is:
;		SAK o...
;	SAK is invoked with the following options:
;		A     -- DO NOT Allow the User to Abort MCL
;		B     -- Ring Bell
;		Pnnnn -- Pause nnnn seconds and continue if no
;			 response by that time
;
	ext	print, condin, eval10, pause, cline, cout, phldc

tbuff	equ	80h	;command line buffer
cr	equ	0dh
lf	equ	0ah
ctrlc	equ	'C'-'@'
ctrlg	equ	'G'-'@'

;
;	This program is Copyright (c) 1983 by Richard Conn
;	All Rights Reserved
;
;	ZCPR2 and its utilities, including this one, are released
; to the public domain.  Anyone who wishes to USE them may do so with
; no strings attached.  The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;
;	The author, Richard Conn, has sole rights to this program.
; ZCPR2 and its utilities may not be sold without the express,
; written permission of the author.
;

;
;  Branch to Start of Program
;
	jmp	start

;
;******************************************************************
;
;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
;	This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;

;
;  EXTERNAL PATH DATA
;
EPAVAIL:
	DB	0FFH	; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
	DW	40H	; ADDRESS OF EXTERNAL PATH IF AVAILABLE

;
;  INTERNAL PATH DATA
;
INTPATH:
	DB	0,0	; DISK, USER FOR FIRST PATH ELEMENT
			; DISK = 1 FOR A, '$' FOR CURRENT
			; USER = NUMBER, '$' FOR CURRENT
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0	; DISK, USER FOR 8TH PATH ELEMENT
	DB	0	; END OF PATH

;
;  MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
	DB	0FFH	; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
	DW	0FF00H	; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE

;
;  DISK/USER LIMITS
;
MDISK:
	DB	4	; MAXIMUM NUMBER OF DISKS
MUSER:
	DB	31	; MAXIMUM USER NUMBER

;
;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
	DB	0FFH	; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
	DB	0FFH	; ALLOW USER CHANGE? (0=NO, 0FFH=YES)

;
;  PRIVILEGED USER DATA
;
PUSER:
	DB	10	; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
	DB	'chdir',0	; PASSWORD FOR MOVING INTO PRIV USER AREAS
	DS	41-($-PPASS)	; 40 CHARS MAX IN BUFFER + 1 for ending NULL

;
;  CURRENT USER/DISK INDICATOR
;
CINDIC:
	DB	'$'	; USUAL VALUE (FOR PATH EXPRESSIONS)

;
;  DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
	DW	80H	; TBUFF AREA

;
;  NAMED DIRECTORY INFORMATION
;
NDRADR:
	DW	00000H	; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
	DB	64	; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
	DB	'NAMES   '	; NAME OF DISK NAME FILE
	DB	'DIR'		; TYPE OF DISK NAME FILE

;
;  REQUIREMENTS FLAGS
;
EPREQD:
	DB	000H	; EXTERNAL PATH?
MCREQD:
	DB	0FFH	; MULTIPLE COMMAND LINE?
MXREQD:
	DB	000H	; MAX USER/DISK?
UDREQD:
	DB	000H	; ALLOW USER/DISK CHANGE?
PUREQD:
	DB	000H	; PRIVILEGED USER?
CDREQD:
	DB	000H	; CURRENT INDIC AND DMA?
NDREQD:
	DB	000H	; NAMED DIRECTORIES?
Z2CLASS:
	DB	6	; CLASS 6 (for Processor Speed)
	DB	'ZCPR2'
	DS	10	; RESERVED

;
;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;

;
;  ZCPR2 Class 6 Constants
;
pspeed:
	db	4	;Processor Speed in MHz
crtpage:
	db	24	;CRT page Size

;
;  Other Buffers
;
abortf:
	ds	1	;abort flag
bell:
	ds	1	;bell flag
delay:
	ds	2	;delay constant

;
;  Start of Program
;
start:

;
;  Print Banner
;
	call	print
	db	'SAK, Version '
	db	(vers/10)+'0','.',(vers mod 10)+'0',0
;
;  Init Options and Parse and Interpret Command Line
;
	xra	a	;turn options off
	sta	bell	;turn off bell
	sta	delay	;turn off delay (pause)
	sta	delay+1
	mvi	a,0ffh	;turn options on
	sta	abortf	;turn on abort
	lxi	h,tbuff	;save command line
	call	cline
opt:
	mov	a,m	;get option letter
	inx	h	;pt to next
	ora	a	;done?
	jz	optdone
	cpi	' '	;skip spaces
	jz	opt
	cpi	'A'	;abort?
	jz	optabort
	cpi	'B'	;bell?
	jz	optbell
	cpi	'P'	;pause?
	jz	optpause
	call	print
	db	cr,lf,'SAK is invoked by a command line of the following form:'
	db	cr,lf,'	SAK o...'
	db	cr,lf,'where "o..." is zero or more options combined in any '
	db	'order.'
	db	cr,lf,'The options are:'
	db	cr,lf,'	A     -- DO NOT Allow the User to Abort and Clear the '
	db	'MCL Buffer'
	db	cr,lf,'	B     -- Ring the Bell'
	db	cr,lf,'	Pnnnn -- Pause nnnn seconds and then resume '
	db	'automatically'
	db	cr,lf,'SAK allows the user to strike ^C to abort and clear the'
	db	cr,lf,'multiple command line buffer (if there is one) or any'
	db	cr,lf,'other key to continue execution'
	db	cr,lf,0
	ret
;
;  Process A option (Abort MCL)
;
optabort:
	xra	a	;turn off abort
	sta	abortf
	jmp	opt
;
;  Process B option (Ring Bell)
;
optbell:
	mvi	a,0ffh	;turn on bell
	sta	bell
	jmp	opt
;
;  Process Pnnnn option (Pause nnnn seconds)
;
optpause:
	call	eval10	;convert argument to decimal value in DE
	xchg		;HL contains value
	shld	delay
	call	print
	db	cr,lf,'Pause Selected: ',0
	call	phldc	;print in decimal
	call	print
	db	' Second Delay before Resuming',0
	xchg		;HL pts to next char
	jmp	opt
;
;  Continue Command Processing
;
optdone:
	lhld	delay	;get delay count in HL
	lda	abortf	;abort allowed?
	ora	a	;0=no
	jz	noabort
	call	print
	db	cr,lf,'Please Strike ^C to Abort, Any Other Key to '
	db	'Continue - ',0
	jmp	sakloop
noabort:
	call	print
	db	cr,lf,'Please Strike Any Key to Continue - ',0
;
;  Main Delay Loop
;
sakloop:
;
;  Ring Bell if Option Selected
;
	lda	bell	;get flag
	ora	a	;set zero flag
	cnz	bout	;ring bell and delay
;
;  Get character if one is available
;
	call	condin	;optionally get character
	jnz	gotchar	;process character
;
;  Loop if No Delay
;
	mov	a,h	;check for no delay
	ora	l
	jz	sakloop
;
;  Delay and test for input
;
	push	h	;save second counter
	lxi	h,10	;1 full second delay
	lda	pspeed	;get processor speed
	mov	b,a	;... in B
	call	pause	;delay 1 sec
	pop	h	;get second counter
	dcx	h	;count down
	mov	a,h	;done?
	ora	l
	jnz	sakloop
;
;  Process Input Character
;	If no input and timout instead, A=0 for continuation character
;
gotchar:
	cpi	ctrlc	;abort?
	jz	abort
resume:
	call	print
	db	cr,lf,'Resuming ...',0
	ret
;
;  Abort Multiple Command Line if there is one
;
abort:
	lda	abortf	;abort allowed?
	ora	a	;0=no
	jz	resume
	lda	mcavail	;multiple command line available?
	ora	a	;0=no
	jz	abort1
	lhld	mcadr	;get address of buffer
	lxi	d,4	;add 4
	xchg
	dad	d	;HL=MC+4, DE=MC
	mvi	m,0	;set no further command
	xchg		;HL=MC, DE=MC+4 (next command char ptr)
	mov	m,e	;store ptr to next command
	inx	h
	mov	m,d
abort1:
	call	print
	db	cr,lf,'Aborting ...',0
	ret
;
;  Ring Bell and Delay Briefly
;
bout:
	mvi	a,ctrlg	;ring bell
	call	cout
	push	h	;save HL
	lhld	delay	;do not delay if pause already invoked
	mov	a,h	;zero delay?
	ora	l
	jnz	bout1	;skip delay
	lxi	h,4	;0.4 sec delay
	lda	pspeed	;get processor speed
	mov	b,a	;... in B
	call	pause	;delay
bout1:
	pop	h
	ret

	end
